package jnzb.ui;

import java.awt.Font;
import java.text.DecimalFormat;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Spring;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

/**
 * Has details of the current download
 * 
 * @author Rid
 * 
 */
@SuppressWarnings("serial")
public class CurrentPanel extends JPanel {
	// Only keep references to things we want to update
	JLabel file = new JLabel(" ");
	JLabel group = new JLabel(" ");
	JProgressBar fileProgress = new JProgressBar();
	JProgressBar segmentProgress = new JProgressBar();
	JLabel speed = new JLabel(" ");;

	DecimalFormat speedFormatter = (DecimalFormat) DecimalFormat
			.getNumberInstance();

	public CurrentPanel() {
		speedFormatter.applyPattern("#.##");
		create();
	}

	private void create() {
		// Create the border
		Border etchedBorder = BorderFactory
				.createEtchedBorder(EtchedBorder.LOWERED);
		Border titleBorder = BorderFactory.createTitledBorder(etchedBorder,
				"Current Download");
		this.setBorder(titleBorder);

		this.setLayout(new SpringLayout());

		JLabel fileLabel = new JLabel("File", JLabel.TRAILING);
		JLabel groupLabel = new JLabel("Group", JLabel.TRAILING);
		JLabel progressLabel = new JLabel("Progress", JLabel.TRAILING);
		JLabel segmentProgressLabel = new JLabel("Segment", JLabel.TRAILING);
		JLabel speedLabel = new JLabel("Speed", JLabel.TRAILING);

		// Create a new BOLD version of the current font
		Font boldFont = new Font(super.getFont().getName(), Font.BOLD, super
				.getFont().getSize());
		fileLabel.setFont(boldFont);
		groupLabel.setFont(boldFont);
		progressLabel.setFont(boldFont);
		speedLabel.setFont(boldFont);
		segmentProgressLabel.setFont(boldFont);
		
		this.add(fileLabel);
		this.add(file);
		this.add(groupLabel);
		this.add(group);
		this.add(progressLabel);
		this.add(fileProgress);
		this.add(segmentProgressLabel);
		this.add(segmentProgress);
		this.add(speedLabel);
		this.add(speed);

		// Do all spring layout stuff - yes manually, it's easy!
		createLayout(fileLabel, groupLabel, progressLabel,
				segmentProgressLabel, speedLabel);

		// Set the max height to the preferred height
		SwingUtils.fixMaximumPrefefedHeight(this);
	}

	/**
	 * Sets the spring constraints
	 * 
	 * @param speedLabel
	 * @param progressLabel
	 * @param sizeLabel
	 * @param groupLabel
	 * @param fileLabel
	 */
	private void createLayout(JLabel fileLabel, JLabel groupLabel,
			JLabel progressBarLabel, JLabel segmentProgressLabel,
			JLabel speedLabel) {
		SpringLayout layout = (SpringLayout) this.getLayout();

		// Get the constraints for all relevant components
		SpringLayout.Constraints fileCons = layout.getConstraints(this.file);
		SpringLayout.Constraints fileLabelCons = layout
				.getConstraints(fileLabel);

		SpringLayout.Constraints groupCons = layout.getConstraints(this.group);
		SpringLayout.Constraints groupLabelCons = layout
				.getConstraints(groupLabel);

		SpringLayout.Constraints progressCons = layout
				.getConstraints(this.fileProgress);
		SpringLayout.Constraints progressLabelCons = layout
				.getConstraints(progressBarLabel);

		SpringLayout.Constraints segmentProgressCons = layout
				.getConstraints(this.segmentProgress);
		SpringLayout.Constraints segmentProgressLabelCons = layout
				.getConstraints(segmentProgressLabel);

		SpringLayout.Constraints speedCons = layout.getConstraints(this.speed);
		SpringLayout.Constraints speedLabelCons = layout
				.getConstraints(speedLabel);

		// Padding value
		Spring padding = Spring.constant(5);

		// Initialised to the initial X position for the first column
		Spring xPos = Spring.constant(5);

		// Create a column for 4 labels where the max width is that of the
		// progress label
		fileLabelCons.setWidth(progressLabelCons.getWidth());
		groupLabelCons.setWidth(progressLabelCons.getWidth());
		speedLabelCons.setWidth(progressLabelCons.getWidth());
		// progressLabelCons.setWidth(fileLabelCons.getWidth());

		// For x positioning, as this is the first columns, just set to an
		// initial padding of 5 pixels
		// These are the 4 fields that are on the left making a column
		fileLabelCons.setX(xPos);
		groupLabelCons.setX(xPos);
		progressLabelCons.setX(xPos);
		segmentProgressLabelCons.setX(xPos);
		speedLabelCons.setX(xPos);

		// Adjust the X position for the next column - take what we have, add
		// the width of the progress label, plus some padding
		xPos = Spring.sum(xPos, Spring.sum(progressLabelCons.getWidth(),
				padding));

		fileCons.setX(xPos);
		groupCons.setX(xPos);
		progressCons.setX(xPos);
		segmentProgressCons.setX(xPos);
		speedCons.setX(xPos);

		// Set the widths so they are all the same as progress bar
		fileCons.setWidth(progressCons.getWidth());
		// Not sure about number files
		groupCons.setWidth(progressCons.getWidth());
		speedCons.setWidth(progressCons.getWidth());
		segmentProgressCons.setWidth(progressCons.getWidth());

		// Set the final xPos so we can set the container width properly
		// Add where we are + width of form field + padding
		xPos = Spring.sum(xPos, Spring.sum(progressCons.getWidth(), padding));

		// This is our starting Y position
		Spring yPos = Spring.constant(5);

		// Set start pos
		fileCons.setY(yPos);
		fileLabelCons.setY(yPos);

		// Set heights to field height
		fileLabelCons.setHeight(fileCons.getHeight());

		// Sum the yPos with where we are + field height + padding
		yPos = Spring.sum(yPos, Spring.sum(fileCons.getHeight(), padding));

		// Next row
		groupCons.setY(yPos);
		groupLabelCons.setY(yPos);
		groupLabelCons.setHeight(groupCons.getHeight());

		// Sum the yPos with where we are + field height + padding
		yPos = Spring.sum(yPos, Spring.sum(groupCons.getHeight(), padding));

		// Next row
		progressCons.setY(yPos);
		progressLabelCons.setY(yPos);
		progressCons.setHeight(progressLabelCons.getHeight());

		// Sum the yPos with where we are + field height + padding
		yPos = Spring.sum(yPos, Spring.sum(progressLabelCons.getHeight(),
				padding));

		// Next row
		segmentProgressCons.setY(yPos);
		segmentProgressLabelCons.setY(yPos);
		segmentProgressCons.setHeight(segmentProgressLabelCons.getHeight());

		// Sum the yPos with where we are + field height + padding
		yPos = Spring.sum(yPos, Spring.sum(
				segmentProgressLabelCons.getHeight(), padding));

		// Last row
		speedCons.setY(yPos);
		speedLabelCons.setY(yPos);
		speedCons.setHeight(speedLabelCons.getHeight());

		// Sum the yPos with where we are + field height + padding
		yPos = Spring
				.sum(yPos, Spring.sum(speedLabelCons.getHeight(), padding));

		// Set the form panel size size.
		SpringLayout.Constraints formPanelConstraints = layout
				.getConstraints(this);

		formPanelConstraints.setHeight(yPos);
		formPanelConstraints.setWidth(xPos);

		// Apply constraints from the north and east to ensure this container
		// sticks to the top and left
		// xPos & yPos now contain the total widths and heights of the contents
		// of the container
		formPanelConstraints.setConstraint(SpringLayout.NORTH, yPos);
		formPanelConstraints.setConstraint(SpringLayout.EAST, xPos);

	}

	public void setFile(final String fileName) {
		Runnable r = new Runnable() {
			public void run() {
				// Stops the label dissapearing - probably my bad swing setup
				if (fileName == null || fileName.length() == 0) {
					file.setText(" ");
				} else {
					file.setText(fileName);
				}
				file.setToolTipText(fileName);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	public void setGroup(final String groupName) {
		Runnable r = new Runnable() {
			public void run() {
				group.setText(groupName);
				group.setToolTipText(groupName);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	/**
	 * Progress bar is set with a range of 1..numSegments. So, to set progress,
	 * just pass in segment number
	 * 
	 * @param segment
	 */
	public void setProgress(int segment) {
		this.fileProgress.setValue(segment);
	}

	/**
	 * Speed in k/s as a double. This will do the formatting
	 * 
	 * @param speedText
	 */
	public void setSpeed(final double speedks) {
		Runnable r = new Runnable() {
			public void run() {
				speed.setText(speedFormatter.format(speedks) + " k/s");
			}
		};
		SwingUtilities.invokeLater(r);
	}

	/**
	 * Sets total numner of segments in this 'file'. Will setup progress bar
	 * 
	 * @param segments
	 */
	public void setNumberSegments(final int segments) {
		Runnable r = new Runnable() {
			public void run() {
				fileProgress.setMaximum(segments);
				fileProgress.setValue(0);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	/**
	 * Sets the value of the progress bar
	 * 
	 * @param numDownloaded
	 */
	public void setNumSegmentsDownloaded(final int numDownloaded) {
		Runnable r = new Runnable() {
			public void run() {
				fileProgress.setValue(numDownloaded);
			}
		};
		SwingUtilities.invokeLater(r);

	}

	/**
	 * Set the filename. If you pass in an empty string, this will set it to a
	 * space to avoid gui display problems
	 * 
	 * @param filename
	 */
	public void setFilename(String filename) {
		if (filename != null && filename.length() > 0)
			this.file.setText(filename);
		else
			this.file.setText(" ");
	}

	/**
	 * Resets the current download panel to a start state
	 */
	public void resetPanel() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				file.setText(" ");
				group.setText(" ");
				setNumberSegments(0);
				speed.setText(" ");
			}
		};

		SwingUtilities.invokeLater(r);
	}

	/**
	 * Sets the size of this segment, which just sets the range on the segment
	 * progress bar
	 * 
	 * @param size
	 */
	public void setSegmentSize(final int size) {
		Runnable r = new Runnable() {
			public void run() {
				segmentProgress.setMaximum(size);
				segmentProgress.setValue(0);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	/**
	 * Set the segment progress
	 * 
	 * @param speedks
	 */
	public void setDownloaded(final int bytes) {
		Runnable r = new Runnable() {
			public void run() {
				segmentProgress.setValue(bytes);
			}
		};
		SwingUtilities.invokeLater(r);
	}

}
